%Borra todos los hechos existentes de llega(?origen, ?destino, ?tiempo)
retractAllLLega :- retractall(llega(_,_,_)).

%Restablece los hechos de llega(?origen, ?destino, ?tiempo) como están en el código original
restablecerLLega :- 
	retractAllLLega,
	assertz(llega(buenos_aires, mdq, 1)),
	assertz(llega(buenos_aires, cordoba, 2)),
	assertz(llega(buenos_aires, rio, 4)),
	assertz(llega(buenos_aires, madrid, 12)),
	assertz(llega(buenos_aires, atlanta, 11)),
	assertz(llega(mdq, buenos_aires, 1)),
	assertz(llega(cordoba, salta, 1)),
	assertz(llega(salta, buenos_aires, 2)),
	assertz(llega(rio, buenos_aires, 4)),
	assertz(llega(rio, new_york, 10)),
	assertz(llega(atlanta, new_york, 3)),
	assertz(llega(new_york, madrid, 9)),
	assertz(llega(madrid, lisboa, 1)),
	assertz(llega(madrid, buenos_aires, 12)),
	assertz(llega(lisboa, madrid, 1)),
	assertz(llega(new_york, buenos_aires, 11)).

%Borra todos los hechos existentes de autonomia(?avion, ?horas)
retractAllAviones :- retractall(autonomia(_,_)).

%Restablece los hechos de autonomia(?avion, ?horas) como están en el código original
restablecerAviones :- 
	retractAllAviones,
	assertz(autonomia(boeing_767, 15)),
	assertz(autonomia(airbus_a320, 9)),
	assertz(autonomia(boeing_747, 10)).

%============ Tests ciudades(-Ciudades) ============
%Se testea que devuelve las ciudades desde las cuales parte algún vuelo.
testCiudades1 :- 
	retractAllLLega , 
	assertz(llega(buenos_aires,mdq,2)),
		ciudades(C),
		member(buenos_aires,C),
		not(member(mdq,C)),
	restablecerLLega.

testCiudades2 :-
	retractAllLLega , 
	assertz(llega(buenos_aires,mdq,2)),
	assertz(llega(mdq,salta,5)),
		ciudades(C),
		member(buenos_aires,C),
		member(mdq,C),
		not(member(salta,C)),
	restablecerLLega.

testCiudades3 :-
	retractAllLLega , 
	assertz(llega(buenos_aires,mdq,2)),
	assertz(llega(mdq,salta,5)),
	assertz(llega(salta,buenos_aires,3)),
		ciudades(C),
		member(buenos_aires,C),
		member(mdq,C),
		member(salta,C),
	restablecerLLega.

%============ Tests viajeDesde(+Origen,?Destino,-Recorrido,-Tiempo) ============
%Esta cláusula devuelve infinitos resultas, por eso para el test se probaran algunos resultados posibles
%y otros que no pueden serlo.
testViajeDesde1 :-
	retractAllLLega , 
	assertz(llega(buenos_aires,mdq,2)),
	assertz(llega(mdq,salta,5)),
	assertz(llega(salta,buenos_aires,3)),
	assertz(llega(buenos_aires,salta,4)),
		viajeDesde(buenos_aires,mdq,[buenos_aires,mdq],2),
		viajeDesde(buenos_aires,mdq,[buenos_aires,salta,buenos_aires,mdq],9),		
		viajeDesde(buenos_aires,salta,[buenos_aires,mdq,salta],7),
		viajeDesde(buenos_aires,salta,[buenos_aires,salta],4),
		viajeDesde(buenos_aires,salta,[buenos_aires,salta,buenos_aires,salta],11),
		viajeDesde(buenos_aires,buenos_aires,[buenos_aires],0),
		viajeDesde(buenos_aires,buenos_aires,[buenos_aires,mdq,salta,buenos_aires],10),
		viajeDesde(buenos_aires,buenos_aires,[buenos_aires,salta,buenos_aires],7),
		viajeDesde(mdq,buenos_aires,[mdq,salta,buenos_aires],8),
		viajeDesde(mdq,buenos_aires,[mdq,salta,buenos_aires,mdq,salta,buenos_aires],18),
		viajeDesde(mdq,salta,[mdq,salta],5),
		viajeDesde(salta,buenos_aires,[salta,buenos_aires],3),
		viajeDesde(salta,buenos_aires,[salta,buenos_aires,salta,buenos_aires],10),
		viajeDesde(salta,buenos_aires,[salta,buenos_aires,mdq,salta,buenos_aires],13),
		not(viajeDesde(salta,buenos_aires,[salta,buenos_aires],4)),
		not(viajeDesde(salta,buenos_aires,[salta,buenos_aires,mdq],_)),
		not(viajeDesde(salta,buenos_aires,[salta,buenos_aires,mdq,buenos_aires],_)),
	restablecerLLega.

%============ Tests viajeSinCiclos(+Origen,?Destino,-Recorrido,-Tiempo) ============
testViajeSinCiclos1 :-
	retractAllLLega , 
	assertz(llega(buenos_aires,mdq,2)),
	assertz(llega(mdq,salta,5)),
	assertz(llega(salta,buenos_aires,3)),
	assertz(llega(buenos_aires,salta,4)),
		viajeSinCiclos(buenos_aires,buenos_aires,[buenos_aires],0),
		viajeSinCiclos(buenos_aires,mdq,[buenos_aires,mdq],2),		
		not(viajeSinCiclos(buenos_aires,mdq,[buenos_aires,mdq,salta,buenos_aires,mdq],_)),
		viajeSinCiclos(buenos_aires,salta,[buenos_aires,mdq,salta],7),
		viajeSinCiclos(buenos_aires,salta,[buenos_aires,salta],4),
		not(viajeSinCiclos(buenos_aires,salta,[buenos_aires,salta,buenos_aires,salta],_)),
		not(viajeSinCiclos(buenos_aires,salta,[buenos_aires,mdq,salta],8)),		
		viajeSinCiclos(mdq,mdq,[mdq],0),
		viajeSinCiclos(mdq,buenos_aires,[mdq,salta,buenos_aires],8),
		not(viajeSinCiclos(mdq,buenos_aires,[mdq,salta,buenos_aires,salta,buenos_aires],_)),
		not(viajeSinCiclos(mdq,buenos_aires,[mdq,salta,buenos_aires,mdq,salta,buenos_aires],_)),
		viajeSinCiclos(mdq,salta,[mdq,salta],5),
		not(viajeSinCiclos(mdq,salta,[mdq,salta,buenos_aires,salta],_)),
		viajeSinCiclos(salta,salta,[salta],0),
		viajeSinCiclos(salta,buenos_aires,[salta,buenos_aires],3),
		not(viajeSinCiclos(salta,buenos_aires,[salta,buenos_aires,mdq,salta,buenos_aires],_)),		
	restablecerLLega.

%============ Tests viajeMasCorto(+Origen,+Destino,-Recorrido,-Tiempo) ============
%Con este test se ve que es el menor recorrido.
testViajeMasCorto1 :-
	retractAllLLega , 
	assertz(llega(buenos_aires,mdq,2)),
	assertz(llega(mdq,salta,5)),
	assertz(llega(salta,buenos_aires,3)),
	assertz(llega(buenos_aires,salta,14)),
	assertz(llega(salta,mdq,5)),
	assertz(llega(mdq,buenos_aires,11)),
		viajeMasCorto(buenos_aires,mdq,[buenos_aires,mdq],2),
		not(viajeMasCorto(buenos_aires,mdq,[buenos_aires,salta,mdq],_)),
		viajeMasCorto(buenos_aires,salta,[buenos_aires,mdq,salta],7),
		not(viajeMasCorto(buenos_aires,salta,[buenos_aires,salta],_)),
		viajeMasCorto(mdq,buenos_aires,[mdq,salta,buenos_aires],8),
		not(viajeMasCorto(mdq,buenos_aires,[mdq,buenos_aires],_)),
		viajeMasCorto(mdq,salta,[mdq,salta],5),
		not(viajeMasCorto(mdq,salta,[mdq,buenos_aires,salta],_)),
	restablecerLLega.

%Con este test se ve que pueden haber varios como menor recorrido
testViajeMasCorto2 :-
	retractAllLLega , 
	assertz(llega(buenos_aires,salta,5)),
	assertz(llega(buenos_aires,cordoba,3)),
	assertz(llega(cordoba,salta,2)),
	assertz(llega(cordoba,mendoza,3)),
	assertz(llega(mendoza,salta,3)),
	assertz(llega(salta,buenos_aires,5)),
		viajeMasCorto(buenos_aires,salta,[buenos_aires,salta],5),
		viajeMasCorto(buenos_aires,salta,[buenos_aires,cordoba,salta],5),
		not(viajeMasCorto(buenos_aires,salta,[buenos_aires,cordoba,mendoza,salta],_)),		
	restablecerLLega.

%============ Tests grafoCorrecto ============
testGrafoCorrecto1 :-
	retractAllLLega , 
	assertz(llega(cordoba,salta,3)),
		not(grafoCorrecto),		
	restablecerLLega.

testGrafoCorrecto2 :-
	retractAllLLega , 
	assertz(llega(cordoba,salta,3)),
	assertz(llega(salta,cordoba,3)),
		grafoCorrecto,		
	restablecerLLega.

testGrafoCorrecto3 :-
	retractAllLLega , 
	assertz(llega(cordoba,salta,3)),
	assertz(llega(salta,cordoba,3)),
	assertz(llega(salta,mendoza,3)),
		not(grafoCorrecto),		
	restablecerLLega.

testGrafoCorrecto4 :-
	retractAllLLega , 
	assertz(llega(cordoba,salta,3)),
	assertz(llega(salta,cordoba,3)),
	assertz(llega(salta,mendoza,3)),
	assertz(llega(mendoza,san_luis,3)),
		not(grafoCorrecto),		
	restablecerLLega.

testGrafoCorrecto5 :-
	retractAllLLega , 
	assertz(llega(cordoba,salta,3)),
	assertz(llega(salta,cordoba,3)),
	assertz(llega(salta,mendoza,3)),
	assertz(llega(mendoza,san_luis,3)),
	assertz(llega(cordoba,san_luis,3)),
		not(grafoCorrecto),		
	restablecerLLega.

testGrafoCorrecto6 :-
	retractAllLLega , 
	assertz(llega(cordoba,salta,3)),
	assertz(llega(salta,cordoba,3)),
	assertz(llega(salta,mendoza,3)),
	assertz(llega(mendoza,san_luis,3)),
	assertz(llega(cordoba,san_luis,3)),
	assertz(llega(san_luis,salta,3)),
		grafoCorrecto,		
	restablecerLLega.

%============ Tests cubreDistancia(+Recorrido, ?Avion) ============
testCubreDistancia1 :-
	retractAllLLega ,
	retractAllAviones,
	assertz(llega(buenos_aires,salta,5)),
	assertz(llega(buenos_aires,cordoba,3)),
	assertz(llega(cordoba,salta,2)),
	assertz(llega(cordoba,mendoza,3)),
	assertz(llega(mendoza,salta,3)),
	assertz(llega(salta,buenos_aires,5)),
	assertz(autonomia(avion1,10)),
	assertz(autonomia(avion2,5)),
	assertz(autonomia(avion3,3)),
		cubreDistancia([buenos_aires,salta],avion1),
		cubreDistancia([buenos_aires,salta],avion2),
		not(cubreDistancia([buenos_aires,salta],avion3)),		
		cubreDistancia([buenos_aires,cordoba,salta],avion1),
		cubreDistancia([buenos_aires,cordoba,salta],avion2),
		cubreDistancia([buenos_aires,cordoba,salta],avion3),
		cubreDistancia([cordoba,mendoza,salta,buenos_aires],avion1),
		cubreDistancia([cordoba,mendoza,salta,buenos_aires],avion2),
		not(cubreDistancia([cordoba,mendoza,salta,buenos_aires],avion3)),
	restablecerLLega,
	restablecerAviones.

%============ Tests vueloSinTransbordo(+Aerolinea, +Ciudad1, +Ciudad2, ?Tiempo, ?Avion) ============
testVueloSinTransbordo1 :-
	retractAllLLega,
	retractAllAviones,
	assertz(llega(buenos_aires, cordoba, 2)),
	assertz(llega(cordoba, salta, 2)),
	assertz(llega(buenos_aires, salta, 5)),
	assertz(llega(salta, buenos_aires, 5)),
	assertz(autonomia(avion1,3)),
	assertz(autonomia(avion2,6)),
		vueloSinTransbordo([(buenos_aires,[avion1])],buenos_aires,salta,4,avion1),
		vueloSinTransbordo([(buenos_aires,[avion2])],buenos_aires,salta,4,avion2),
		vueloSinTransbordo([(buenos_aires,[avion1,avion2])],buenos_aires,salta,4,avion1),
		vueloSinTransbordo([(buenos_aires,[avion1,avion2])],buenos_aires,salta,4,avion2),
		vueloSinTransbordo([(salta,[avion2]),(buenos_aires,[avion1])],buenos_aires,salta,4,avion1),
	restablecerLLega,
	restablecerAviones.

testVueloSinTransbordo2 :-
	retractAllLLega,
	retractAllAviones,
	assertz(llega(buenos_aires, cordoba, 2)),
	assertz(llega(cordoba, salta, 3)),
	assertz(llega(buenos_aires, salta, 5)),
	assertz(llega(salta, buenos_aires, 5)),
	assertz(autonomia(avion1,3)),
	assertz(autonomia(avion2,6)),
		vueloSinTransbordo([(buenos_aires,[avion1])],buenos_aires,salta,5,avion1),
		vueloSinTransbordo([(buenos_aires,[avion2])],buenos_aires,salta,5,avion2),
	restablecerLLega,
	restablecerAviones.
	
testVueloSinTransbordo3 :-
	retractAllLLega,
	retractAllAviones,
	assertz(llega(buenos_aires, cordoba, 3)),
	assertz(llega(cordoba, salta, 3)),
	assertz(llega(buenos_aires, salta, 5)),
	assertz(llega(salta, buenos_aires, 5)),
	assertz(autonomia(avion1,3)),
	assertz(autonomia(avion2,6)),
		vueloSinTransbordo([(buenos_aires,[avion1])],buenos_aires,salta,6,avion1),
	restablecerLLega,
	restablecerAviones.	
	
% ===================
runAllSuitTests :-
	testCiudades1,
	testCiudades2,
	testCiudades3,
	testViajeDesde1,
	testViajeSinCiclos1,
	testViajeMasCorto1,
	testViajeMasCorto2,
	testGrafoCorrecto1,
	testGrafoCorrecto2,
	testGrafoCorrecto3,
	testGrafoCorrecto4,
	testGrafoCorrecto5,
	testGrafoCorrecto6,
	testCubreDistancia1,
	testVueloSinTransbordo1,
	testVueloSinTransbordo2,
	testVueloSinTransbordo3.